using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace QiHe.CodeLib
{
    public class DataGridViewHelper<T>
    {
        DataGridView TheDataGridView;
        string ColumnPrefix;

        public DataGridViewHelper(DataGridView dataGridView)
        {
            TheDataGridView = dataGridView;
            ColumnPrefix = null;
        }

        public DataGridViewHelper(DataGridView dataGridView, string columnPrefix)
        {
            TheDataGridView = dataGridView;
            ColumnPrefix = columnPrefix;
        }

        public void AddRowData(T data)
        {
            int index = TheDataGridView.Rows.Add();
            DataGridViewRow row = TheDataGridView.Rows[index];
            SetRowData(row, data);
        }

        public List<T> GetDataList()
        {
            List<T> dataList = new List<T>();
            foreach (DataGridViewRow row in TheDataGridView.Rows)
            {
                if (!row.IsNewRow)
                {
                    dataList.Add(GetRowData(row));
                }
            }
            return dataList;
        }

        public void SetDataList(IEnumerable<T> dataList)
        {
            TheDataGridView.Rows.Clear();
            foreach (T data in dataList)
            {
                AddRowData(data);
            }
        }

        public T GetRowData(DataGridViewRow row)
        {
            T data = Activator.CreateInstance<T>();
            foreach (FieldInfo field in typeof(T).GetFields())
            {
                field.SetValue(data, row.Cells[ColumnPrefix + field.Name].Value);
            }
            return data;
        }

        public void SetRowData(DataGridViewRow row, T data)
        {
            foreach (FieldInfo field in typeof(T).GetFields())
            {
                row.Cells[ColumnPrefix + field.Name].Value = field.GetValue(data);
            }
        }

        public List<int> GetSelectedRowIndice()
        {
            int count = TheDataGridView.SelectedRows.Count;
            if (count == 0) return null;
            List<int> selectedRowIndice = new List<int>(count);
            foreach (DataGridViewRow selectedRow in TheDataGridView.SelectedRows)
            {
                selectedRowIndice.Add(selectedRow.Index);
            }
            selectedRowIndice.Sort();
            return selectedRowIndice;
        }

        public static void SwapRowContent(DataGridViewRow firstRow, DataGridViewRow secondRow)
        {
            int count = firstRow.Cells.Count;
            for (int i = 0; i < count; i++)
            {
                object tempValue = firstRow.Cells[i].Value;
                firstRow.Cells[i].Value = secondRow.Cells[i].Value;
                secondRow.Cells[i].Value = tempValue;
            }
        }

        public void DeleteSelectedRows()
        {
            foreach (DataGridViewRow row in TheDataGridView.SelectedRows)
            {
                TheDataGridView.Rows.Remove(row);
            }
        }

        public void MoveSelectedRowsUp()
        {
            List<int> selectedRowIndice = GetSelectedRowIndice();
            if (selectedRowIndice == null) return;
            if (selectedRowIndice[0] == 0) return;
            foreach (int index in selectedRowIndice)
            {
                DataGridViewRow selectedRow = TheDataGridView.Rows[index];
                DataGridViewRow previousRow = TheDataGridView.Rows[index - 1];
                SwapRowContent(selectedRow, previousRow);
                previousRow.Selected = true;
                selectedRow.Selected = false;
            }
        }

        public void MoveSelectedRowsDown()
        {
            List<int> selectedRowIndice = GetSelectedRowIndice();
            if (selectedRowIndice == null) return;
            selectedRowIndice.Reverse();
            if (selectedRowIndice[0] == TheDataGridView.Rows.Count - 1) return;
            foreach (int index in selectedRowIndice)
            {
                DataGridViewRow selectedRow = TheDataGridView.Rows[index];
                DataGridViewRow nextRow = TheDataGridView.Rows[index + 1];
                SwapRowContent(selectedRow, nextRow);
                nextRow.Selected = true;
                selectedRow.Selected = false;
            }
        }

        public void MoveSelectedRowsTop()
        {
            List<int> selectedRowIndice = GetSelectedRowIndice();
            if (selectedRowIndice == null) return;
            while (selectedRowIndice[0] > 0)
            {
                MoveSelectedRowsUp();
                selectedRowIndice = GetSelectedRowIndice();
            }
        }

        public void MoveSelectedRowsBottom()
        {
            List<int> selectedRowIndice = GetSelectedRowIndice();
            if (selectedRowIndice == null) return;
            while (selectedRowIndice[selectedRowIndice.Count - 1] < TheDataGridView.Rows.Count - 1)
            {
                MoveSelectedRowsDown();
                selectedRowIndice = GetSelectedRowIndice();
            }
        }
    }
}
